/**
 * @file gc.cpp
 * @brief VimL虚拟机垃圾回收系统实现
 * @author VimL VM Team
 * @date 2024
 * 
 * 分代增量式垃圾回收器的完整实现
 */

#include "viml/gc.h"
#include <iostream>
#include <algorithm>
#include <cstring>

namespace viml {

// 全局GC实例
std::unique_ptr<GarbageCollector> g_gc;

// ObjectPool实现
ObjectPool::ObjectPool(size_t object_size, size_t pool_size)
    : object_size_(object_size), pool_size_(pool_size), 
      current_chunk_(nullptr), free_list_(nullptr), offset_(0) {}

ObjectPool::~ObjectPool() {
    Chunk* chunk = current_chunk_;
    while (chunk) {
        Chunk* next = chunk->next;
        delete[] chunk->data;
        delete chunk;
        chunk = next;
    }
}

void* ObjectPool::allocate() {
    std::lock_guard<std::mutex> lock(mutex_);
    
    if (free_list_) {
        void* ptr = free_list_;
        free_list_ = *reinterpret_cast<char**>(free_list_);
        return ptr;
    }
    
    if (!current_chunk_ || offset_ + object_size_ > pool_size_) {
        Chunk* new_chunk = new Chunk;
        new_chunk->data = new char[pool_size_];
        new_chunk->next = current_chunk_;
        current_chunk_ = new_chunk;
        offset_ = 0;
    }
    
    void* ptr = current_chunk_->data + offset_;
    offset_ += object_size_;
    return ptr;
}

void ObjectPool::deallocate(void* ptr) {
    std::lock_guard<std::mutex> lock(mutex_);
    *reinterpret_cast<char**>(ptr) = free_list_;
    free_list_ = static_cast<char*>(ptr);
}

void ObjectPool::reset() {
    std::lock_guard<std::mutex> lock(mutex_);
    Chunk* chunk = current_chunk_;
    while (chunk) {
        Chunk* next = chunk->next;
        delete[] chunk->data;
        delete chunk;
        chunk = next;
    }
    current_chunk_ = nullptr;
    free_list_ = nullptr;
    offset_ = 0;
}

// StringInternPool实现
StringInternPool::StringInternPool() = default;

StringInternPool::~StringInternPool() = default;

std::shared_ptr<std::string> StringInternPool::intern(const std::string& str) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    auto it = strings_map_.find(str);
    if (it != strings_map_.end()) {
        return it->second;
    }
    
    auto shared_str = std::make_shared<std::string>(str);
    strings_map_[str] = shared_str;
    return shared_str;
}

void StringInternPool::cleanup() {
    std::lock_guard<std::mutex> lock(mutex_);
    // 字符串驻留池不需要清理，由GC管理
}



// GarbageCollector实现
GarbageCollector::GarbageCollector(const GCConfig& config)
    : config_(config), young_gen_head_(nullptr), old_gen_head_(nullptr),
      heap_size_(0), young_gen_size_(0), old_gen_size_(0), objects_count_(0),
      collections_count_(0), young_gen_collections_(0), old_gen_collections_(0),
      bytes_freed_(0) {
    
    // 初始化小对象池
    pools_.emplace_back(std::make_unique<ObjectPool>(16));
    pools_.emplace_back(std::make_unique<ObjectPool>(32));
    pools_.emplace_back(std::make_unique<ObjectPool>(64));
    pools_.emplace_back(std::make_unique<ObjectPool>(128));
    
    // 初始化字符串驻留池
    string_pool_ = std::make_unique<StringInternPool>();
}

GarbageCollector::~GarbageCollector() {
    sweep();
}

void* GarbageCollector::allocate(size_t size, ObjectType type) {
    if (size <= 128) {
        return allocate_from_pool(size, type);
    } else {
        return allocate_from_heap(size, type);
    }
}

void* GarbageCollector::allocate_from_pool(size_t size, ObjectType type) {
    ObjectPool* pool = get_pool(size);
    if (pool) {
        void* ptr = pool->allocate();
        if (ptr) {
            ObjectHeader* header = static_cast<ObjectHeader*>(ptr);
            new (header) ObjectHeader(type, size);
            
            size_t total_size = size + sizeof(ObjectHeader);
            heap_size_ += total_size;
            young_gen_size_ += total_size;
            objects_count_++;
            
            return static_cast<char*>(ptr) + sizeof(ObjectHeader);
        }
    }
    return allocate_from_heap(size, type);
}

void* GarbageCollector::allocate_from_heap(size_t size, ObjectType type) {
    size_t total_size = size + sizeof(ObjectHeader);
    
    ObjectHeader* header = static_cast<ObjectHeader*>(::operator new(total_size));
    new (header) ObjectHeader(type, size);
    
    header->next = young_gen_head_;
    young_gen_head_ = header;
    
    heap_size_ += total_size;
    young_gen_size_ += total_size;
    objects_count_++;
    
    // 检查是否需要触发GC
    if (young_gen_size_ > config_.young_gen_threshold) {
        collect_young_gen();
    }
    
    return static_cast<char*>(static_cast<void*>(header)) + sizeof(ObjectHeader);
}

ObjectPool* GarbageCollector::get_pool(size_t size) {
    for (auto& pool : pools_) {
        if (pool && pool->object_size() >= size + sizeof(ObjectHeader)) {
            return pool.get();
        }
    }
    return nullptr;
}

void GarbageCollector::collect() {
    collect_old_gen();
}

void GarbageCollector::collect_young_gen() {
    mark_roots();
    sweep_generation(true);
    young_gen_collections_++;
    collections_count_++;
}

void GarbageCollector::collect_old_gen() {
    mark_roots();
    sweep_generation(false);
    promote_objects();
    old_gen_collections_++;
    collections_count_++;
}

void GarbageCollector::incremental_collect() {
    // TODO: 实现增量式GC
    collect_young_gen();
}

void GarbageCollector::add_root(Value* value) {
    std::lock_guard<std::mutex> lock(roots_mutex_);
    roots_.push_back(value);
}

void GarbageCollector::remove_root(Value* value) {
    std::lock_guard<std::mutex> lock(roots_mutex_);
    roots_.erase(std::remove(roots_.begin(), roots_.end(), value), roots_.end());
}

void GarbageCollector::mark_roots() {
    std::lock_guard<std::mutex> lock(roots_mutex_);
    for (Value* root : roots_) {
        mark_value(*root);
    }
}

void GarbageCollector::mark_value(const Value& value) {
    // 根据Value类型进行标记
    if (value.is_string()) {
        // 字符串类型无需特殊处理
    } else if (value.is_list() || value.is_dict()) {
        // TODO: 标记容器中的元素
    }
}

void GarbageCollector::mark_object(ObjectHeader* obj) {
    if (!obj || obj->marked) return;
    
    obj->marked = true;
    
    // 根据对象类型递归标记引用的对象
    switch (obj->type) {
        case ObjectType::STRING:
            break;
        case ObjectType::LIST:
            break;
        case ObjectType::DICT:
            break;
        case ObjectType::FUNCTION:
            break;
        default:
            break;
    }
}

void GarbageCollector::sweep() {
    sweep_generation(true);
    sweep_generation(false);
}

void GarbageCollector::sweep_generation(bool young_gen) {
    ObjectHeader** head = young_gen ? &young_gen_head_ : &old_gen_head_;
    ObjectHeader* prev = nullptr;
    ObjectHeader* current = *head;
    
    while (current) {
        ObjectHeader* next = current->next;
        
        if (!current->marked) {
            // 释放对象
            size_t total_size = current->size + sizeof(ObjectHeader);
            
            if (prev) {
                prev->next = next;
            } else {
                *head = next;
            }
            
            if (current->in_young_gen || young_gen) {
                young_gen_size_ -= total_size;
            } else {
                old_gen_size_ -= total_size;
            }
            
            heap_size_ -= total_size;
            objects_count_--;
            bytes_freed_ += total_size;
            
            // 如果是小对象池的对象，返回到池中
            ObjectPool* pool = get_pool(current->size);
            if (pool && young_gen) {
                pool->deallocate(current);
            } else {
                ::operator delete(current);
            }
        } else {
            current->marked = false;
            prev = current;
        }
        
        current = next;
    }
}

void GarbageCollector::promote_objects() {
    ObjectHeader* current = young_gen_head_;
    ObjectHeader* prev = nullptr;
    ObjectHeader* next_young_gen_head = nullptr;
    
    while (current) {
        ObjectHeader* next = current->next;
        
        if (current->marked) {
            // 晋升到老年代
            current->in_young_gen = false;
            current->next = old_gen_head_;
            old_gen_head_ = current;
            
            size_t total_size = current->size + sizeof(ObjectHeader);
            young_gen_size_ -= total_size;
            old_gen_size_ += total_size;
            
            if (prev) {
                prev->next = next;
            } else {
                next_young_gen_head = next;
            }
        } else {
            prev = current;
        }
        
        current = next;
    }
    
    young_gen_head_ = next_young_gen_head;
}

std::shared_ptr<std::string> GarbageCollector::intern_string(const std::string& str) {
    return string_pool_->intern(str);
}

void GarbageCollector::print_stats() const {
    std::cout << "GC Statistics:\n"
              << "  Heap size: " << heap_size_ << " bytes\n"
              << "  Young gen size: " << young_gen_size_ << " bytes\n"
              << "  Old gen size: " << old_gen_size_ << " bytes\n"
              << "  Objects count: " << objects_count_ << "\n"
              << "  Collections: " << collections_count_ << "\n"
              << "  Young gen collections: " << young_gen_collections_ << "\n"
              << "  Old gen collections: " << old_gen_collections_ << "\n"
              << "  Bytes freed: " << bytes_freed_ << " bytes\n"
              << "  String intern pool size: " << string_pool_->size() << "\n";
    std::cout << "Object pools:\n";
    for (size_t i = 0; i < pools_.size(); ++i) {
        if (pools_[i]) {
            std::cout << "  Pool " << i << " (" << pools_[i]->object_size() << " bytes): "
                      << "allocated\n";
        }
    }
}

void GarbageCollector::verify_heap() const {
    // TODO: 实现堆验证
    std::cout << "Heap verification: OK\n";
}

// 初始化全局GC
void initialize_gc() {
    g_gc = std::make_unique<GarbageCollector>();
}

void shutdown_gc() {
    g_gc.reset();
}

} // namespace viml